医疗葡萄糖注射液袋漏取检测


主页      博客     


项目背景
葡萄糖注射液袋装入托盘进行干燥后,会进行翻转放置在生产线上进行传送,但是部分药袋粘在托盘上无法掉落,如果不去掉则会混入下一批次。
下图是一张采用背光的相机采集图片:
sample_actual_0.png
难点:
1. 托盘是不锈钢的,无论正面还是侧面都会反光很严重。
stainless_steel_reflection.jpg
2. 现场环境光变化大,会影响相机采集图像的亮度,从而影响边缘。
enviroment_light_up.jpg

实验
下面是测试结果:
test_result.gif
下面是参考代码:

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
#include <stdio.h>   // for use getchar();
#include <stdlib.h>   // system("pause");
#include <string>

using namespace cv;
using namespace std;

Mat src, imageSource, threshold_dst, gray_dst, morphology_dst;
int const max_elem = 2;
int const max_kernel_size = 21;
int morph_elem = 0;
int morph_size = 0;
int morph_operator = 0;
int max_operator = 4;
const char* window_name = "Morphology Transformations Demo";
int threshold_elem = 127;
int64 t[30] = { 0 };
double ft[30] = { 0.0 };
double fCPU[30] = { 1000 };
VideoCapture cap;
char filename[80];
int iImage = 629;
int nextImage = 0;
int nextImage1 = 0;
int i;

void findCountour(void)
{
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	
	findContours(threshold_dst, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
	
	Mat imageContours = Mat::zeros(threshold_dst.size(), CV_8UC1);
	Mat display;
	Mat Contours = Mat::zeros(threshold_dst.size(), CV_8UC1); //绘制
	src.copyTo(display);
	for (int i = 0; i<contours.size(); i++)
	{
		/*
		//contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数
		for (int j = 0; j<contours[i].size(); j++)
		{
			//绘制出contours向量内所有的像素点
			Point P = Point(contours[i][j].x, contours[i][j].y);
			Contours.at<uchar>(P) = 255;
		}
		*/
		drawContours(imageContours, contours, i, Scalar(255), 3, 8, hierarchy);
		drawContours(display, contours, i, Scalar(0, 0, 255), 3, 8, hierarchy);
	}

	imshow("Contours Image", imageContours); //轮廓
	//imshow("Point of Contours", Contours); //向量contours内保存的所有轮廓点集
	imshow("Source Image", display);

}
void Morphology_Operations(int, void*)
{
	// Since MORPH_X : 2,3,4,5 and 6
	int operation = morph_operator + 2;
	Mat element = getStructuringElement(morph_elem, Size(2 * morph_size + 1, 2 * morph_size + 1), Point(morph_size, morph_size));

	//sprintf(filename, "E:/Basler/Cisen203/Basler_acA1300-30gc__21751999__20200520_144409942_%d.tiff", iImage);
	//src = imread(filename);
	imshow("Source Image", src);
	//src.copyTo(imageSource);

	morphologyEx(imageSource, morphology_dst, operation, element);

	imshow(window_name, morphology_dst);

	cvtColor(morphology_dst, gray_dst, COLOR_BGR2GRAY);

	threshold(gray_dst, threshold_dst, threshold_elem, 255, 0);

	imshow("Threshold", threshold_dst);

	findCountour();

}
void Threshold_Operations(int, void*)
{
	threshold(gray_dst, threshold_dst, threshold_elem, 255, 0);
	imshow("Threshold", threshold_dst);
	findCountour();
}

int main(int argc, char *argv[])

{
	/*
	src = imread("D:/Project/Basler/OpenCV/ConsoleApplication1/cisen1.png");
	imshow("Source Image", src);
	src.copyTo(imageSource);
	*/
	
	cap.open("I:/Basler_acA1300-30gc__21751999__20200520_150933492.avi");
	cap >> src;
	src.copyTo(imageSource);
	int width = cap.get(CV_CAP_PROP_FRAME_WIDTH);  //帧宽度
	int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //帧高度
	int frameRate = cap.get(CV_CAP_PROP_FPS);  //帧率 x frames/s
	int totalFrames = cap.get(CV_CAP_PROP_FRAME_COUNT); //总帧数

	cout << "视频宽度=" << width << endl;
	cout << "视频高度=" << height << endl;
	cout << "视频总帧数=" << totalFrames << endl;
	cout << "帧率=" << frameRate << endl;
	
	namedWindow("Source Image", WINDOW_NORMAL); // Create window
	resizeWindow("Source Image", 640, 640);
	namedWindow("Contours Image", WINDOW_NORMAL); // Create window
	resizeWindow("Contours Image", 640, 640);
	//namedWindow("Point of Contours", WINDOW_NORMAL); // Create window
	//resizeWindow("Point of Contours", 640, 640);
	namedWindow(window_name, WINDOW_NORMAL); // Create window
	resizeWindow(window_name, 640, 640);
	namedWindow("Threshold", WINDOW_NORMAL); // Create window
	resizeWindow("Threshold", 640, 640);
	createTrackbar("Operator:\n 0: Opening - 1: Closing  \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations);
	createTrackbar("Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
		&morph_elem, max_elem,
		Morphology_Operations);
	createTrackbar("Kernel size:\n 2n +1", window_name,
		&morph_size, max_kernel_size,
		Morphology_Operations);
	createTrackbar("Next", window_name,
		&nextImage, 1,
		Morphology_Operations);
	Morphology_Operations(0, 0);

	createTrackbar("threshold", "Threshold", &threshold_elem, 255, Threshold_Operations);
	Threshold_Operations(0, 0);
	waitKey(5000);
	while (1)
	{
		i++;
		if (nextImage==1)
		{
			//iImage++;
			if (iImage > 763)iImage = 629;
			cap >> src;
			src.copyTo(imageSource);
			if (src.empty())
			{
				break;
			}
			Morphology_Operations(0, 0);
			
		}
		if (waitKey(10) >= 0)
			break;
	}
/*	Mat frameFast, frameSlow;
	while (1)
	{
		if (waitKey(0) == 27)
			break;
		else if (waitKey(0) == 13)
		{
			cap >> src;
			src.copyTo(imageSource);
			if (src.empty())
			{
				//i = 1;
				break;
			}
			Morphology_Operations(0, 0);
		}

	}   */




	waitKey(0);
	system("Pause");
	return 0;

}